﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using UtilZ.Dotnet.Ex.Model;

namespace UtilZ.Dotnet.Ex.Communication.Ports
{
    /// <summary>
    /// 串口基类
    /// </summary>
    public abstract class SerialPortAbs : ISerialPort
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public SerialPortAbs()
        {

        }

        /// <summary>
        /// 原始串口对象
        /// </summary>
        public abstract object OriginSerialPort { get; }

        /// <summary>
        /// 指示串口对象打开或关闭状态
        /// </summary>
        public abstract bool IsOpen { get; }

        /// <summary>
        /// 获取接收缓冲区中数据字节数
        /// </summary>
        public abstract int BytesToRead { get; }

        /// <summary>
        /// 从输入缓冲区读取一些字节,并将读取到的字节写入字节数组指定的偏移量处
        /// </summary>
        /// <param name="buffer">将输入写入到其中的字节数据</param>
        /// <param name="offset">要写入字节buffer中偏移量</param>
        /// <param name="count">最多读取的字节数,如果count大于输入缓冲区中的字节数,则读取较少的字节</param>
        /// <returns>读取的字节数</returns>
        public abstract int Read(byte[] buffer, int offset, int count);

        /// <summary>
        /// 打开一个新的串行端口连接
        /// </summary>
        public abstract void Open();


        /// <summary>
        /// 将指定的字符串写入串行端口
        /// 异常:
        /// T:System.InvalidOperationException:指定的端口未打开。
        /// T:System.ServiceProcess.TimeoutException:该操作未在超时时间到期之前完成。
        /// </summary>
        /// <param name="text">输出字符串</param>
        public abstract void Send(string text);

        /// <summary>
        /// 使用缓冲区的数据将指定数量的字节写入串行端口
        /// 异常:
        /// T:System.InvalidOperationException:指定的端口未打开。
        /// T:System.ArgumentOutOfRangeException:offset 或 count 参数超出了所传递的 buffer 的有效区域。offset 或 count 小于零。
        /// T:System.ArgumentException:offset 加上 count 大于 buffer 的长度。
        /// T:System.ServiceProcess.TimeoutException:该操作未在超时时间到期之前完成。
        /// </summary>
        /// <param name="buffer">包含要写入端口的数据的字节数组</param>
        /// <param name="offset">buffer 参数中从零开始的字节偏移量，从此处开始将字节复制到端口</param>
        /// <param name="size">要写入的字节数</param>
        public abstract void Send(byte[] buffer, int offset, int size);

        /// <summary>
        /// 使用缓冲区的数据将指定数量的字符写入串行端口
        /// 异常:
        /// T:System.InvalidOperationException:指定的端口未打开。
        /// T:System.ArgumentOutOfRangeException: offset 或 count 参数超出了所传递的 buffer 的有效区域。offset 或 count 小于零。
        /// T:System.ArgumentException:offset 加上 count 大于 buffer 的长度。
        /// T:System.ServiceProcess.TimeoutException:该操作未在超时时间到期之前完成。
        /// </summary>
        /// <param name="buffer">包含要写入端口的数据的字符数组</param>
        /// <param name="offset">buffer 参数中从零开始的字节偏移量，从此处开始将字节复制到端口</param>
        /// <param name="size">要写入的字符数</param>
        public abstract void Send(char[] buffer, int offset, int size);

        /// <summary>
        /// 将指定的字符串和 System.IO.Ports.SerialPort.NewLine 值写入输出缓冲区
        /// 异常:
        /// T:System.InvalidOperationException:指定的端口未打开。
        /// T:System.TimeoutException:System.IO.Ports.SerialPort.WriteLine(System.String) 方法未能写入流。
        /// </summary>
        /// <param name="text">写入输出缓冲区的字符串</param>
        public abstract void SendLine(string text);

        /// <summary>
        /// 关闭串口连接,将IsOpen设置为false,并释放内部资源
        /// </summary>
        public abstract void Close();

        /// <summary>
        /// 
        /// </summary>
        public abstract void Dispose();



        /// <summary>
        /// 串口上发生了错误事件
        /// </summary>
        [MonitoringDescription("SerialErrorReceived")]
        public event EventHandler<EventArgs<SerialPortError>> ErrorReceived;

        private EventArgs<SerialPortError> _errorReceivedArgs = null;
        /// <summary>
        /// 触发串口上发生了错误事件
        /// </summary>
        /// <param name="error">错误</param>
        protected void OnRaiseErrorReceived(SerialPortError error)
        {
            var handler = this.ErrorReceived;
            if (handler != null)
            {
                if (this._errorReceivedArgs == null)
                {
                    this._errorReceivedArgs = new EventArgs<SerialPortError>();
                }
                this._errorReceivedArgs.Para = error;
                handler(this, this._errorReceivedArgs);
            }
        }

        /// <summary>
        /// 串口上发生了非数据信号事件
        /// </summary>
        [MonitoringDescription("SerialPinChanged")]
        public event EventHandler<EventArgs<SerialPortPinChange>> PinChanged;

        private EventArgs<SerialPortPinChange> _pinChangedArgs = null;
        /// <summary>
        /// 触发串口上发生了非数据信号事件
        /// </summary>
        protected void OnRaisePinChanged(SerialPortPinChange change)
        {
            var handler = this.PinChanged;
            if (handler != null)
            {
                if (this._pinChangedArgs == null)
                {
                    this._pinChangedArgs = new EventArgs<SerialPortPinChange>();
                }
                this._pinChangedArgs.Para = change;
                handler(this, this._pinChangedArgs);
            }
        }

        /// <summary>
        /// 指示串口已接收到数据事件
        /// </summary>
        [MonitoringDescription("SerialDataReceived")]
        public event EventHandler<EventArgs<SerialPortData>> DataReceived;

        private EventArgs<SerialPortData> _dataReceivedArgs = null;
        /// <summary>
        /// 触发串口上发生了非数据信号事件
        /// </summary>
        protected void OnRaiseDataReceived(SerialPortData data)
        {
            var handler = this.DataReceived;
            if (handler != null)
            {
                if (this._dataReceivedArgs == null)
                {
                    this._dataReceivedArgs = new EventArgs<SerialPortData>();
                }
                this._dataReceivedArgs.Para = data;
                handler(this, this._dataReceivedArgs);
            }
        }
    }
}
